/**
 *
 *                              Program/Module                                   
 *                                   from                                        
 *                 Selfverifying Solvers for Dense Systems of                    
 *                     Linear Equations Realized in C-XSC                        
 *                                                                               
 *                     Carlos Holbig and Walter Kraemer, 2003.                   
 *                                                                               
 *       Program developed in C-XSC by Bernardo Frederes Kramer Alcalde,         
 *           Paulo Sergio Morandi Junior and Carlos Amaral Holbig                
 *                                                                               
 * Purpose: Compute approximations to the solution x of Ax = b and an            
 *    approximations of the inverse of A. In both case the system (m x n) can be 
 *    square (m = n), over-determined (m > n) and under-determined (m < n).      
 */

#ifndef _MANAGERLSS_HPP
#define _MANAGERLSS_HPP

#include <iostream>
#include <iomanip>       // for I/O manipulation
#include <mpi.h>
#include <pthread.h>
#include <imatrix.hpp>   // Include real and interval types for Vector/Matrix
#include <mvi_util.hpp>  // Include real and interval utilities for Vector/Matrix
#include "../parallel/IminusAB.h"
#include "../parallel/CalculateDR2temp.h"
#include "../parallel/IminusABminusCB.h"
#include "../utils.h"
#include "../GaussJordan/lss_aprx.hpp"  // Include library for matrix inversion
#include "../GaussJordan/GaussJordan.hpp"
#include "lss_utils.hpp"
#include <fstream>

#define REPETICOES 3

using namespace cxsc;
using namespace std;

class ManagerLss {
	public:
		ManagerLss();
		ManagerLss(rmatrix&, rvector&, ivector&, int, int, int);
		~ManagerLss();

		int startLss(void);
		int getRank(void);
		int getWorldCommSize(void);
		int getNumThreads(void);
		
		rmatrix& getA(void);
		rvector& getB(void);
		ivector& getLssResult(void);
	private:
		int nRows, nCols;
		int systemType;
		int rank, worldCommSize;
		int numThreads;
		rmatrix &userA, &sysA;
		rvector &userB, &sysB;
		ivector &userY, &sysY;
		
		void setRank(int);
		void setWorldCommSize(int);
		void setNumThreads(int);
		
		void setSystemType(int);
		int getSystemType(void);
		void over_lss(void);
		void under_lss(void);
		int square_lss(void);
		
		int compute_single_r(rmatrix&, rmatrix&);
		int compute_double_r(rmatrix&, rmatrix&);
};

#endif
